﻿from dbnew import postgre, mysql, firebird, odbc, oracle

class FdbRelations:
	"This class is a manipulator for RDB$RELATIONS in firebird"
	#beginning of class suite
	#print (FdbRelations.__doc__)
	#Инициализация:
	def __init__(self):
		#Методу fdb присваивается экземпляр класса firebird
		self.fdb=firebird()
		self.log=None

	#Определяется базовая функция подсчета количества таблиц и видов
	def count(self,type,names):
		'''Function counts relations'''
		#beginning of function suite
		#print(self.count.__doc__)
		#Переменной query присваивается None
		query=''
		#Если аргумент names не равен ['']:
		if names!=['']:
			#Переменной query присваивается соответствующее условие sql запроса:
			query=" AND TRIM(RDB$RELATION_NAME) IN ('"+"','".join(names)+"')"
		#Выполняется подключение к базе данных
		self.fdb.connect()
		#Выполняется транзакция подсчета строк с заданными именами
		self.fdb.cursor.execute("SELECT COUNT (*) FROM RDB$RELATIONS WHERE RDB$SYSTEM_FLAG=0 AND RDB$RELATION_TYPE IN "+type+query)
		#Переменной result присваивается результат
		result=self.fdb.cursor.fetchall()[0][0]
		#Закрывается подключение к базе данных
		self.fdb.disconnect()
		#В переменную класса log записывается лог
		self.log='counted'
		#end of function suite
		#Функция возвращает число таблиц и видов с заданными именами
		return result
	
	#Определяется функция подсчета количества таблиц
	def CountTables(self,names=['']):
		'''Function counts tables'''
		#beginning of function suite
		#print(self.CountTables.__doc__)
		#end of function suite
		#Функция возвращает число таблиц с заданными именами
		return self.count('(0)',names)

	#Определяется функция подсчета количества видов
	def CountViews(self,names=['']):
		'''Function counts views'''
		#beginning of function suite
		#print(self.CountViews.__doc__)
		#end of function suite
		#Функция возвращает число видов с заданными именами
		return self.count('(1)',names)

	#Определяется функция подсчета количества таблиц и видов
	def CountAny(self,names=['']):
		'''Function counts any'''
		#beginning of function suite
		#print(self.CountAny.__doc__)
		#end of function suite
		#Функция возвращает число таблиц и видов с заданными именами
		return self.count('(0,1)',names)

	#Определяется базовая функция подсчета количества похожих таблиц и видов
	def countlike(self,type,names):
		'''Function counts like relations'''
		#beginning of function suite
		#print(self.countlike.__doc__)
		#Переменной query присваивается None
		result=0
		#Выполняется подключение к базе данных
		self.fdb.connect()
		for name in names:
			#К значению переменной name добавляются %
			name='%'+name+'%'
			#Выполняется транзакция подсчета строк с заданным именем
			self.fdb.cursor.execute("SELECT COUNT (*) FROM RDB$RELATIONS WHERE RDB$SYSTEM_FLAG=0 AND RDB$RELATION_TYPE IN "+type+" AND TRIM(RDB$RELATION_NAME) LIKE ?",[name])
			#К переменной result прибавляется результат
			result=result+self.fdb.cursor.fetchall()[0][0]
		#Закрывается подключение к базе данных
		self.fdb.disconnect()
		#В переменную класса log записывается лог
		self.log='counted'
		#end of function suite
		#Функция возвращает число таблиц и видов с похожими именами
		return result

	#Определяется функция подсчета количества похожих таблиц
	def CountlikeTables(self,names=['']):
		'''Function counts tables'''
		#beginning of function suite
		#print(self.CountlikeTables.__doc__)
		#end of function suite
		#Функция возвращает число таблиц с похожим именами
		return self.countlike('(0)',names)

	#Определяется функция подсчета количества похожих видов
	def CountlikeViews(self,names=['']):
		'''Function counts views'''
		#beginning of function suite
		#print(self.CountlikeViews.__doc__)
		#end of function suite
		#Функция возвращает число видов с похожим именами
		return self.countlike('(1)',names)

	#Определяется функция подсчета количества похожих таблиц и видов
	def CountlikeAny(self,names=['']):
		'''Function counts any'''
		#beginning of function suite
		#print(self.CountlikeAny.__doc__)
		#end of function suite
		#Функция возвращает число таблиц и видов с похожим именами
		return self.countlike('(0,1)',names)

	#Определяется базовая функция выборки таблиц и видов
	def select(self,type,names):
		'''Function counts relations'''
		#beginning of function suite
		#print(self.CountViews.__doc__)
		#Переменной query присваивается None
		query=''
		#Если аргумент names не равен ['%']
		if names!=['']:
			#Переменной query присваивается соответствующее условие sql запроса:
			query=" AND TRIM(RDB$RELATION_NAME) IN ('"+"','".join(names)+"')"
		#Выполняется подключение к базе данных
		self.fdb.connect()
		#Выполняется транзакция подсчета строк с заданными именами
		self.fdb.cursor.execute("SELECT * FROM RDB$RELATIONS WHERE RDB$SYSTEM_FLAG=0 AND RDB$RELATION_TYPE IN "+type+query)
		#Переменной result присваивается результат
		result=self.fdb.cursor.fetchall()
		#Закрывается подключение к базе данных
		self.fdb.disconnect()
		#В переменную класса log записывается лог
		self.log='selected'
		#end of function suite
		#Функция возвращает число таблиц и видов с заданными именами
		return result
		
	#Определяется функция выборки таблиц
	def SelectTables(self,names=['']):
		'''Function selects tables'''
		#beginning of function suite
		#print(self.SelectTables.__doc__)
		#end of function suite
		#Функция возвращает выборку таблиц с заданными именами
		return self.select('(0)',names)

	#Определяется функция выборки видов
	def SelectViews(self,names=['']):
		'''Function selects views'''
		#beginning of function suite
		#print(self.SelectViews.__doc__)
		#end of function suite
		#Функция возвращает выборку видов с заданными именами
		return self.select('(1)',names)
		
	#Определяется функция выборки таблиц и видов
	def SelectAny(self,names=['']):
		'''Function selects any'''
		#beginning of function suite
		#print(self.SelectAny.__doc__)
		#end of function suite
		#Функция возвращает выборку таблиц и видов с заданными именами
		return self.select('(0,1)',names)
	
	#Определяется базовая функция выборки похожих таблиц и видов
	def selectlike(self,type,names):
		'''Function selects like relations'''
		#beginning of function suite
		#print(self.selectlike.__doc__)
		#Переменной query присваивается None
		result=[]
		#Выполняется подключение к базе данных
		self.fdb.connect()
		for name in names:
			#К значению переменной name добавляются %
			name='%'+name+'%'
			#Выполняется транзакция подсчета строк с заданным именем
			self.fdb.cursor.execute("SELECT * FROM RDB$RELATIONS WHERE RDB$SYSTEM_FLAG=0 AND RDB$RELATION_TYPE IN "+type+" AND TRIM(RDB$RELATION_NAME) LIKE ?",[name])
			#К переменной result прибавляется результат
			result=result+self.fdb.cursor.fetchall()
		#Закрывается подключение к базе данных
		self.fdb.disconnect()
		#В переменную класса log записывается лог
		self.log='selected'
		#end of function suite
		#Функция возвращает число видов и таблиц с похожими именами
		return result
		
	#Определяется функция выборки похожих таблиц
	def SelectlikeTables(self,names=['']):
		'''Function selects like tables'''
		#beginning of function suite
		#print(self.SelectlikeTables.__doc__)
		#end of function suite
		#Функция возвращает выборку таблиц с похожими именами
		return self.selectlike('(0)',names)

	#Определяется функция выборки похожих видов
	def SelectlikeViews(self,names=['']):
		'''Function selects like views'''
		#beginning of function suite
		#print(self.SelectlikeViews.__doc__)
		#end of function suite
		#Функция возвращает выборку видов с похожими именами
		return self.selectlike('(1)',names)
	
		#Определяется функция выборки похожих таблиц и видов
	def SelectlikeAny(self,names=['']):
		'''Function selects like any'''
		#beginning of function suite
		#print(self.SelectlikeAny.__doc__)
		#end of function suite
		#Функция возвращает выборку таблиц и видов с похожими именами
		return self.selectlike('(0,1)',names)
	
	#end of FdbRelations class suite

class FdbView:
	"This class is a base class to manipulate a view in firebird"
	#beginning of class suite
	#print (FdbView.__doc__)
	#Инициализация методов класса
	def __init__(self):
		self.fdb=firebird()
		self.FdbRelations=FdbRelations()
		self.log=None
		self.name=''
		self.fields=[]
		self.query=''
	
	def SqlName(self):
		"Function returns sql string for the view name"
		return 'X_OASUP_'+self.name
		
	def SqlFields(self):
		"Function returns sql string for the view fields"
		return ' '+'('+', '.join(self.fields)+')'
		
	def SqlCreate(self):
		"Function returns sql string for the view create query"
		return "CREATE VIEW "+self.SqlName()+self.SqlFields()+" AS "+self.query+";"
		
	def SqlDrop(self):
		"Function returns sql string for the view drop query"
		return "DROP VIEW "+self.SqlName()+";"
		
	def count(self):
		'''Function counts views with the name of the view'''
		#beginning of function suite
		#print(self.count.__doc__)
		#end of function suite
		#Функция возвращает результат выполнения функции self.FdbArticlesToImport.CountViews() с именем вида в качестве аргумента
		return self.FdbRelations.CountViews([self.SqlName()])
		
	def create(self):
		'''Function creates the view '''
		#beginning of function suite
		#print(FdbArticlesToImport.create.__doc__)
		#Подсчетывается количество видов с данным именем
		before=self.count()
		#Если количество=0
		if before==0:
			#Выполняется подключение к базе данных
			self.fdb.connect()
			# Выполняется запрос на создание вида в Firebird:
			self.fdb.cursor.execute(self.SqlCreate())
			#commit
			self.fdb.conn.commit()
			#Закрывается подключение к базе данных
			self.fdb.disconnect()
			#Подсчетывается количество видов с данным именем
			result=self.count()-before
			#В переменную класса log записывается лог
			self.log='created'
		else:
			#Переменной result присваивается нулевое значение
			result=0
			#В переменную класса log записывается лог
			self.log='exists'
		#end of function suite
		#Функция возвращает количество созданных видов
		return result

	def drop(self):
		'''Function drops the view'''
		#beginning of function suite
		#print(FdbArticlesToImport.drop.__doc__)
		#Подсчетывается количество видов с данным именем
		before=self.count()
		#Если количество не равно нулю:
		if before!=0:
			#Выполняется подключение к базе данных
			self.fdb.connect()
			# Выполняется запрос на удаление вида в Firebird:
			self.fdb.cursor.execute(self.SqlDrop())
			#commit
			self.fdb.conn.commit()
			#Закрывается подключение к базе данных
			self.fdb.disconnect()
			#Подсчетывается количество видов с данным именем
			result=before-self.count()
			self.log='droped'
		else:
			#Переменной result присваивается нулевое значение
			result=0
			#В переменную класса log записывается лог
			self.log='does not exist'
		#end of function suite
		#Функция возвращает количество уничтоженных видов
		return result

class ArticlesToImport(FdbView):
	"This class is a manipulator for articles to import in firebird"
	#beginning of class suite
	#print (FdbArticlesToImport.__doc__)
	def __init__(self):
		super(ArticlesToImport, self).__init__()
		self.name='ARTICLES_TO_IMPORT'
		self.fields=['art_id', 'section_id', 'sectname', 'doc_type', 'doc_name', 'designatio', 'name', 'note', 'mu_id', 'purchased', 'format', 'modifdate', 'version_id']
		self.query='''select 

DISTINCT 

a.art_id, a.section_id, ss.sectname, d.doc_type, e.doc_name, a.designatio, a.name, a.note, a.mu_id, a.purchased, d.format, a.modifdate, d.version_id

     FROM articles a, articles_view av, archives ar, pc, ssections ss, doclist d, doctypes e

          WHERE
               
               e.doc_type=d.doc_type
      
               AND d.doc_id=a.doc_id
               
               AND a.section_id=ss.section_id

               AND extract(YEAR from a.chkindate)>2005

               AND a.art_id>0

               AND ar.archive_id=av.archive_id

               AND (ar.archive_id=31
                        OR ar.archive_id=34
                        OR ar.archive_id=35
                        OR ar.archive_id=36
                        OR ar.archive_id=37
                        OR ar.archive_id=38
                        OR ar.archive_id=41
                        OR ar.archive_id=42
                        OR ar.archive_id=43)

               AND CHAR_LENGTH(TRIM(a.name))>0

               AND 

                (
                 (a.art_id=pc.part_aid
                  OR a.art_id=pc.proj_aid)

                 AND av.art_id=pc.proj_aid
                 AND CHAR_LENGTH(TRIM(a.designatio))>0
                 AND (a.SECTION_ID=1
                          OR a.SECTION_ID=3
                          OR a.SECTION_ID=4
                          OR a.SECTION_ID=8)
                )

UNION ALL

select 

DISTINCT 

a.art_id, a.section_id, ss.sectname, d.doc_type, e.doc_name, a.designatio, a.name, a.note, a.mu_id, a.purchased, d.format, a.modifdate, d.version_id

     FROM 

articles a, articles_view av, archives ar, pc, ssections ss, doclist d, doctypes e

          WHERE
               
               e.doc_type=d.doc_type
      
               AND d.doc_id=a.doc_id

               AND a.section_id=ss.section_id

               AND extract(YEAR from a.chkindate)>2005

               AND a.art_id>0

               AND ar.archive_id=av.archive_id

               AND (ar.archive_id=31
                        OR ar.archive_id=34
                        OR ar.archive_id=35
                        OR ar.archive_id=36
                        OR ar.archive_id=37
                        OR ar.archive_id=38
                        OR ar.archive_id=41
                        OR ar.archive_id=42
                        OR ar.archive_id=43)

               AND CHAR_LENGTH(TRIM(a.name))>0

               AND 
                
                (
                 a.art_id=pc.part_aid
                 AND av.art_id=pc.proj_aid
                 AND CHAR_LENGTH(TRIM(a.designatio))=0
                 AND (a.SECTION_ID=5
                          OR a.SECTION_ID=6
                          OR a.SECTION_ID=7)
                )'''
